//Memory.scala
package mycore

import chisel3._
import chisel3.util._

class Memory extends Module{
  val io = IO(new Bundle{

    val ENABLE = Input(Bool())
    val exmem = Flipped(new EXMEM)
    val memwb = new MEMWB
    val DataLoad = new DataLoad
    val DataStore = new DataStore
    val redesMem = new WBDATA
    val TimeOver = Output(Bool())
  })

  //本流水级需要使用的信号
  val mems = RegEnable(io.exmem, WireInit(0.U.asTypeOf(new EXMEM())), io.ENABLE)
  val Valid = mems.Valid
  val Inst = mems.Inst
  val PC = mems.PC
  val isa = mems.isa
  val imm = mems.imm
  val rs1 = mems.Inst(19,15)
  val rs2 = mems.Inst(24,20)
  val src1 = mems.src1
  val src2 = mems.src2
  val csr = mems.csr
  /*------------------------------*/
  /*             本体             */
  /*------------------------------*/
  val lsu = Module(new LoadStoreUnit)
  lsu.io.Valid := Valid
  lsu.io.isa := isa
  lsu.io.src1 := src1
  lsu.io.src2 := src2
  lsu.io.imm := imm
  val load_data = lsu.io.load_data

  val clint = Module(new CoreLocalInterruptor)
  clint.io.Valid := Valid
  clint.io.ClintLoad <> lsu.io.DataLoad
  clint.io.ClintStore <> lsu.io.DataStore
  io.DataLoad <> clint.io.DataLoad
  io.DataStore <> clint.io.DataStore

  val isLoad = lsu.io.DataLoad.en
  val memWbdata = mems.aluresult | mems.link | mems.auipc | mems.csrData
  io.redesMem.wen     := Mux(isLoad, true.B, mems.wen) && Valid
  io.redesMem.regdes  := Mux(isLoad, mems.regdes, mems.regdes)
  io.redesMem.data    := Mux(isLoad, load_data, memWbdata)
  /*------------------------------*/

  //传递给下一个流水级的信号
  io.memwb.Valid    := Valid
  io.memwb.Inst     := Inst
  io.memwb.PC       := PC
  io.memwb.isa      := isa
  io.memwb.src1     := src1
  io.memwb.src2     := src2
  io.memwb.imm      := imm
  io.memwb.wen      := mems.wen
  io.memwb.regdes     := mems.regdes
  io.memwb.aluresult  := mems.aluresult
  io.memwb.branch     := mems.branch
  io.memwb.target     := mems.target
  io.memwb.link       := mems.link
  io.memwb.auipc      := mems.auipc
  io.memwb.csrData    := mems.csrData
  io.memwb.loadData   := load_data
  io.memwb.clintValid := clint.io.ClintValid
  io.memwb.TimerInterrupt := mems.TimerInterrupt
  io.memwb.EnvironmentCall := mems.EnvironmentCall
  io.memwb.csr := csr

  io.TimeOver := clint.io.TimeOver

}